package com.eurobcoin.controller;

import java.util.Enumeration;
import java.util.List;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;

import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

import com.eurobcoin.EurobcoinTable;
import com.eurobcoin.balance.UserBalanceManager;
import com.eurobcoin.balance.UserBalanceModel;
import com.eurobcoin.dao.model.UserRole;
import com.eurobcoin.helper.NumberHelper;
import com.eurobcoin.helper.PasswdHelper;
import com.eurobcoin.invite.InviteManager;
import com.eurobcoin.manager.DAOManager;
import com.eurobcoin.user.UserConst;
import com.eurobcoin.user.UserManager;
import com.eurobcoin.user.UserModel;

@Controller
@RequestMapping("/users")
@SessionAttributes({"usuarios"})
public class UsersController {
	
	private static final Logger logger = LoggerFactory.getLogger(UsersController.class);
	
	private static final String USUARIOS_VIEW = "usuarios";
	private static final String USUARIOS_NUEVO_VIEW = "nuevo_usuario";
	private static final String USUARIOS_BALANCE = "balance";
	
	@Autowired
	private DAOManager daoManager;
	
	@Autowired
	private UserManager userManager;
	
	@Autowired
	private InviteManager inviteManager;
	
	@Autowired
	private UserBalanceManager userBalanceManager;
	
	@ModelAttribute("usuarios")
	public EurobcoinTable createUsuarios() {
		return new EurobcoinTable();
	}
	
	@RequestMapping(value="/list.html", method=RequestMethod.GET)
	public ModelAndView doIndex(
			@ModelAttribute(value="usuarios") EurobcoinTable usuarios, 
			@RequestParam(value="page", required=false) Integer page) throws Exception {
		
		if(page == null)
			page = new Integer(1);
		
		ModelAndView ret = new ModelAndView(USUARIOS_VIEW);
		
		SqlSession sqlSession = this.daoManager.openSession();
		
		this.userManager.getPagedUserList(sqlSession, usuarios, page);
		
		sqlSession.close();
		
		return ret;
		
	}
	
	@RequestMapping(value="/new.html", method=RequestMethod.GET)
	public ModelAndView doNewUser() throws Exception {
		
		ModelAndView ret = new ModelAndView(USUARIOS_NUEVO_VIEW);
		
		SqlSession sqlSession = this.daoManager.openSession();
		
		List<UserRole> roles = this.userManager.getUserRoles(sqlSession);
		ret.addObject("roles", roles);
		
		String salt = PasswdHelper.generateSalt();
		ret.addObject("salt", salt);
		
		ret.addObject("edit_mode", "new");
		sqlSession.close();
		
		return ret;
		
	}
	
	@RequestMapping(value="/edit_user.html", method=RequestMethod.GET)
	public ModelAndView editUser(
			@RequestParam(value="id") Integer id) throws Exception {
		
		ModelAndView ret = new ModelAndView(USUARIOS_NUEVO_VIEW);
		
		SqlSession sqlSession = this.daoManager.openSession();
		
		UserModel user = this.userManager.getUserById(sqlSession, id);
		
		ret.addObject("user", user);
		
		List<UserRole> roles = this.userManager.getUserRoles(sqlSession);
		ret.addObject("roles", roles);
		
		ret.addObject("edit_mode", "edit");
		
		sqlSession.close();
		
		return ret;
	}
	
	@RequestMapping(value="/update_existing_user.html", method=RequestMethod.POST)
	public ModelAndView updateExistingUser(
			@RequestParam(value="name") String name,
			@RequestParam(value="email") String email,
			@RequestParam(value="email_confirmed", required=false) String emailConfirmed,
			@RequestParam(value="locale") String locale,
			@RequestParam(value="rol") Integer rol,
			@RequestParam(value="userId") Integer userId) throws Exception {
		
		boolean bEmailConfirmed = "on".equals(emailConfirmed);
		
		ModelAndView ret = new ModelAndView(USUARIOS_NUEVO_VIEW);
		
		SqlSession sqlSession = this.daoManager.openSession();
		
		boolean commit = false;
		
		this.userManager.updateUser(sqlSession, userId, name, email, bEmailConfirmed, locale, rol); 
		
		commit = true;
		
		UserModel userModel = this.userManager.getUserById(sqlSession, userId);
		ret.addObject("user", userModel);
		
		List<UserRole> roles = this.userManager.getUserRoles(sqlSession);
		ret.addObject("roles", roles);
		
		ret.addObject("edit_mode", "edit");
		
		String message = "Los datos del usuarios se han actualizado con éxito.";
		ret.addObject("message", message);
		
		if(commit)
			sqlSession.commit();
		
		sqlSession.close();
		
		return ret;
		
	}
	
	@RequestMapping(value="/update_user_password.html", method=RequestMethod.POST)
	public ModelAndView updateUserPassword(
			@RequestParam(value="updPasswd") String password,
			@RequestParam(value="userId") Integer userId) throws Exception {
		
		ModelAndView ret = new ModelAndView(USUARIOS_NUEVO_VIEW);
		
		boolean commit = false;
		SqlSession sqlSession = this.daoManager.openSession();
		
		this.userManager.updateUserPassword(sqlSession, userId, password);
		
		commit = true;
		
		UserModel userModel = this.userManager.getUserById(sqlSession, userId);
		ret.addObject("user", userModel);
		
		List<UserRole> roles = this.userManager.getUserRoles(sqlSession);
		ret.addObject("roles", roles);
		
		ret.addObject("edit_mode", "edit");
		
		String message = "La contraseña del usuario se ha actualizado con éxito.";
		ret.addObject("message", message);
		
		if(commit)
			sqlSession.commit();
		
		sqlSession.close();
		
		return ret;
		
	}
	
	@RequestMapping(value="/save_new_user.html", method=RequestMethod.POST)
	public ModelAndView saveNewUser(
			@RequestParam(value="salt") String salt,
			@RequestParam(value="hashedPasswd") String hashedPassword,
			@RequestParam(value="name") String name,
			@RequestParam(value="email") String email,
			@RequestParam(value="email_confirmed", required=false) String emailConfirmed,
			@RequestParam(value="locale") String locale,
			@RequestParam(value="password") String password,
			@RequestParam(value="rol") Integer rol,
			@ModelAttribute(value="usuarios") EurobcoinTable usuarios) throws Exception {
		
		boolean commit = false;
		
		boolean bEmailConfirmed = "on".equalsIgnoreCase(emailConfirmed);
		email = email.toLowerCase();
		name = name.toLowerCase();
		
		ModelAndView ret = new ModelAndView(USUARIOS_VIEW);
		
		SqlSession sqlSession = this.daoManager.openSession();
		
		int retCode = this.userManager.saveUser(
				sqlSession, 
				salt, 
				hashedPassword, 
				name, 
				email, 
				bEmailConfirmed, 
				locale, 
				rol,
				0);
		
		String msg = null;
		
		if(retCode == UserConst.USR_SAVE_OK) {
			commit = true;
			msg = "El usuario se ha almacenado con éxito.";
		}else if(retCode == UserConst.USR_SAVE_REPEATED_EMAIL) {
			commit = false;
			msg = "Este email ya se encuentra registrado en la BBDD.";
		}else if(retCode == UserConst.USR_SAVE_REPEATED_USERNAME) {
			commit = false;
			msg = "Este nombre de usuario ya se encuentra registrado en la BBDD.";
		}
		
		if(commit)
			sqlSession.commit();
		
		ret.addObject("message", msg);
		
		this.userManager.getPagedUserList(sqlSession, usuarios, usuarios.getSelectedPage());
		
		sqlSession.close();
		
		return ret;
		
	}
	
	@RequestMapping(value="/balance.html", method=RequestMethod.GET)
	public ModelAndView showBalance(
			@RequestParam(value="userId") Integer userId) throws Exception {
		
		ModelAndView ret = new ModelAndView(USUARIOS_BALANCE);
		
		SqlSession sqlSession = this.daoManager.openSession();
		
		List<UserBalanceModel> userBalanceModel = this.userBalanceManager.getUserBalanceById(sqlSession, userId, new Locale("es"));
		ret.addObject("balance", userBalanceModel);
		
		ret.addObject("userId", userId);
		
		sqlSession.close();
		
		return ret;
		
	}
	
	@RequestMapping(value="/update_balance.html", method=RequestMethod.POST)
	public ModelAndView updateBalance(
			@RequestParam(value="userId") Integer userId,
			HttpServletRequest request) throws Exception {
		
		ModelAndView ret = new ModelAndView(USUARIOS_BALANCE);
		
		SqlSession sqlSession = this.daoManager.openSession();
		
		Enumeration<String> paramNames = request.getParameterNames();
		while(paramNames.hasMoreElements()) {
			String paramName = paramNames.nextElement();
			if(paramName.startsWith("currency_")) {
				String paramValue = request.getParameter(paramName);
				
				int currencyId = Integer.parseInt(paramName.substring("currency_".length()));
				int currencyDecimals = this.userBalanceManager.getCurrencyDecimals(sqlSession, currencyId);
				
				long newBalance = NumberHelper.stringToLong(paramValue, currencyDecimals, new Locale("es"));
				
				this.userBalanceManager.updateUserBalance(
						sqlSession, 
						userId, 
						currencyId, 
						newBalance);
			}
		}
		
		List<UserBalanceModel> userBalanceModel = this.userBalanceManager.getUserBalanceById(sqlSession, userId, new Locale("es"));
		ret.addObject("balance", userBalanceModel);
		
		String msg = "El balance del usuario se ha actualizado con éxito.";
		ret.addObject("message", msg);
		
		ret.addObject("userId", userId);
		
		sqlSession.commit();
		sqlSession.close();
		
		return ret;
		
	}
			
}
